home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
TECHNICA
/
COMPUTER
/
H254.ZIP
/
IRITSM3S.ZIP
/
CAGD_LIB
/
CAGD_ARC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-26
|
5KB
|
131 lines
/******************************************************************************
* Cagd_Arc.c - Curve representation of arcs and circles *
*******************************************************************************
* Written by Gershon Elber, Jun. 90. *
******************************************************************************/
#ifdef __MSDOS__
#include <stdlib.h>
#endif /* __MSDOS__ */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "cagd_loc.h"
#define UNIT_CIRCLE_ORDER 3
#define UNIT_CIRCLE_LENGTH 9 /* Nine control points in the unit circle. */
static int UnitCircleKnots[UNIT_CIRCLE_ORDER + UNIT_CIRCLE_LENGTH] =
{ 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 };
static int UnitCircleX[UNIT_CIRCLE_LENGTH] = { 1, 1, 0, -1, -1, -1, 0, 1, 1 };
static int UnitCircleY[UNIT_CIRCLE_LENGTH] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
/******************************************************************************
* Creates an arc at the specified position as a rational Bezier curve. *
* The arc is assumed to be less than 180 degrees from Start to End in the *
* shorter path as arc where Center as arc center. *
******************************************************************************/
CagdCrvStruct *BzrCrvCreateArc(CagdPtStruct *Start, CagdPtStruct *Center,
CagdPtStruct *End)
{
int i;
CagdCrvStruct
*Arc = BzrCrvNew(3, CAGD_PT_P3_TYPE);
CagdRType Len, CosAlpha, Radius,
**Points = Arc -> Points;
CagdVecStruct V1, V2, V;
/* Copy first point. */
Points[X][0] = Start -> Pt[0];
Points[Y][0] = Start -> Pt[1];
Points[Z][0] = Start -> Pt[2];
Points[W][0] = 1.0;
/* Copy last point. */
Points[X][2] = End -> Pt[0];
Points[Y][2] = End -> Pt[1];
Points[Z][2] = End -> Pt[2];
Points[W][2] = 1.0;
/* Compute position of middle point. */
Len = 0.0;
for (i = 0; i < 3; i++) {
V1.Vec[i] = Start -> Pt[i] - Center -> Pt[i];
V2.Vec[i] = End -> Pt[i] - Center -> Pt[i];
V.Vec[i] = V1.Vec[i] + V2.Vec[i];
Len += SQR(V.Vec[i]);
}
if (APX_EQ(Len, 0.0)) {
CagdCrvFree(Arc);
FATAL_ERROR(CAGD_ERR_180_ARC);
return NULL;
}
else
Len = sqrt(Len);
for (i = 0; i < 3; i++) V.Vec[i] /= Len;
/* Compute cosine alpha (where alpha is the angle between V and V1. */
Radius = sqrt(DOT_PROD(V1.Vec, V1.Vec));
CosAlpha = DOT_PROD(V1.Vec, V.Vec) / Radius;
CAGD_DIV_VECTOR(V, CosAlpha);
CAGD_MULT_VECTOR(V, Radius);
/* And finally fill in the middle point with CosAlpha as the Weight. */
Points[X][1] = (Center -> Pt[0] + V.Vec[0]) * CosAlpha;
Points[Y][1] = (Center -> Pt[1] + V.Vec[1]) * CosAlpha;
Points[Z][1] = (Center -> Pt[2] + V.Vec[2]) * CosAlpha;
Points[W][1] = CosAlpha;
return Arc;
}
/******************************************************************************
* Creates a circle at the specified position as a rational Bspline curve. *
* Construct a circle as 4 90 degrees arcs of rationa bezier segments using *
* the constants defined above. *
******************************************************************************/
CagdCrvStruct *BspCrvCreateUnitCircle(void)
{
int i;
CagdRType Weight,
W45 = sin( M_PI / 4.0 );
CagdCrvStruct
*Circle = BspCrvNew(UNIT_CIRCLE_LENGTH, UNIT_CIRCLE_ORDER,
CAGD_PT_P3_TYPE);
CagdRType
**Points = Circle -> Points;
for (i = 0; i < UNIT_CIRCLE_LENGTH + UNIT_CIRCLE_ORDER; i++)
Circle -> KnotVector[i] = UnitCircleKnots[i];
for (i = 0; i < UNIT_CIRCLE_LENGTH; i++) {
Weight = Points[W][i] = i % 2 ? W45: 1.0;
Points[X][i] = UnitCircleX[i] * Weight;
Points[Y][i] = UnitCircleY[i] * Weight;
Points[Z][i] = 0.0;
}
return Circle;
}
/******************************************************************************
* Creates a circle at the specified position as a rational bezier curve. *
******************************************************************************/
CagdCrvStruct *BspCrvCreateCircle(CagdPtStruct *Center, CagdRType Radius)
{
CagdPtStruct OriginPt;
CagdCrvStruct *Circle = BspCrvCreateUnitCircle();
/* Do it in two stages: 1. scale, 2. translate */
OriginPt.Pt[0] = OriginPt.Pt[1] = OriginPt.Pt[2] = 0.0;
CagdCrvTransform(Circle, OriginPt.Pt, Radius);
CagdCrvTransform(Circle, Center -> Pt, 1.0);
return Circle;
}